package top.huxy.boot.config.schedule;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import top.huxy.boot.annotation.Operation;
import top.huxy.boot.config.RedisKeyConfig;
import top.huxy.boot.service.ExceptionLogService;
import top.huxy.boot.service.ScheduleService;
import top.huxy.boot.service.impl.OperationLogServiceImpl;
import top.huxy.boot.service.impl.VisitLogServiceImpl;
import top.huxy.boot.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * @Classname LogSchedule
 * @Description 关于日志的一些操作
 * @Date 2021/9/18 12:05
 * @Created by huxy
 */
@Component
public class LogSchedule {

    @Autowired
    VisitLogServiceImpl visitLogService;

    @Autowired
    ExceptionLogService exceptionLogService;

    @Autowired
    OperationLogServiceImpl operationLogService;

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    ScheduleService scheduleService;

    /**
     * 将redis缓存中的访客日志持久化到数据库
     *
     * @return
     */
    @Operation("保存访客日志")
    public String saveTodayVisitLog() {
        Boolean ok;
        try {
            ok = redisTemplate.opsForValue().setIfAbsent(RedisKeyConfig.LOCK_SAVE_VISITOR_LOG, "ok", 30L, TimeUnit.SECONDS);
        } catch (Exception e) {
            return "锁对象获取异常，请稍后再试";
        }
        if (ok == null || !ok) {
            return "未获取到锁对象，请稍后再试";
        }
        try {
            return visitLogService.saveVisitLog();
        } finally {
            //释放锁
            redisTemplate.delete(RedisKeyConfig.LOCK_SAVE_VISITOR_LOG);
        }
    }

    /**
     * 将redis缓存中的异常日志持久化到数据库
     *
     * @return
     */
    @Operation("保存异常日志")
    public String saveTodayExceptionLog() {
        Boolean ok;
        try {
            ok = redisTemplate.opsForValue().setIfAbsent(RedisKeyConfig.LOCK_SAVE_EXCEPTION_LOG, "ok", 30L, TimeUnit.SECONDS);
        } catch (Exception e) {
            return "锁对象获取异常，请稍后再试";
        }
        if (ok == null || !ok) {
            return "未获取到锁对象，请稍后再试";
        }
        try {
            return exceptionLogService.saveRedisExceptionLog2DB();
        } finally {
            //释放锁
            redisTemplate.delete(RedisKeyConfig.LOCK_SAVE_EXCEPTION_LOG);
        }

    }

    @Operation("保存操作日志")
    public String saveTodayOperationLog() {
        Boolean ok;
        try {
            ok = redisTemplate.opsForValue().setIfAbsent(RedisKeyConfig.LOCK_SAVE_OPERATION_LOG, "ok", 30L, TimeUnit.SECONDS);
        } catch (Exception e) {
            return "锁对象获取异常，请稍后再试";
        }
        if (ok == null || !ok) {
            return "未获取到锁对象，请稍后再试";
        }
        try {
            return operationLogService.saveRedisOperationLog2DB();
        } finally {
            //释放锁
            redisTemplate.delete(RedisKeyConfig.LOCK_SAVE_OPERATION_LOG);
        }
    }

    @Operation("批量执行任务")
    public String runAll(String string) {
        if (StringUtils.isEmpty(string)) throw new RuntimeException("任务必须有参数");

        StringBuilder stringBuilder = new StringBuilder();

        ArrayList<Integer> list = new ArrayList<>();

        //解析任务id
        String[] split = string.split(",");
        for (String s : split) {
            try {
                list.add(Integer.parseInt(s));
            } catch (Exception e) {
                //id解析失败，记录日志
                stringBuilder.append(StringUtils.getStackTrace(e)).append("\n");
            }
        }
        if (list.size() == 0) return stringBuilder.append("没有执行任何任务，因为list.size==0").toString();

        stringBuilder.append("准备执行任务:").append(Arrays.toString(split)).append("\n");

        //记录开始时间
        long time_start = System.currentTimeMillis();

        //依次执行任务
        list.forEach(id -> {
            try {
                scheduleService.runOnce(id);
                stringBuilder.append("任务").append(id).append("执行完成\n");
            } catch (Exception e) {
                //任务执行失败，记录日志
                stringBuilder.append(StringUtils.getStackTrace(e)).append("\n");
            }
        });

        //执行完成，记录时间
        long time_end = System.currentTimeMillis();

        stringBuilder.append("执行消耗").append(time_end - time_start).append("毫秒");
        return stringBuilder.toString();
    }
}
